package com.xhwl.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhwl.common.dto.cent.sdata.AccountDetailDTO;
import com.xhwl.common.dto.cent.sdata.EnterpriseConfigDTO;
import com.xhwl.common.enums.LogOperationTypeEnum;
import com.xhwl.common.enums.config.Unit;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.*;
import com.xhwl.common.query.cent.sdata.EnterpriseQuery;
import com.xhwl.common.utils.ThreadLocalUtil;
import com.xhwl.data.dao.IEnterpriseAppConfigDao;
import com.xhwl.data.dao.IEnterpriseConfigDao;
import com.xhwl.data.dao.IEnterpriseDao;
import com.xhwl.data.dao.IThemeConfigDao;
import com.xhwl.data.service.*;
import com.xhwl.starter.log.LogTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author: lrp
 * @Description：企业个性化配置
 * @Date: 16:11 2021/10/11
 */
@Service
public class EnterpriseConfigServiceImpl extends ServiceImpl<IEnterpriseConfigDao, EnterpriseConfig> implements IEnterpriseConfigService {

    private static final Logger log = LoggerFactory.getLogger(EnterpriseConfigServiceImpl.class);
    private final static Integer ENT_SESSION_LIMIT_TIME = 30;
    private final static Integer ENT_SESSION_LIMIT_TIME_UNIT = Unit.MINUTE.code;

    @Autowired
    private IEnterpriseConfigDao enterpriseConfigDao;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private IEnterpriseDao enterpriseDao;

    @Autowired
    private IThemeConfigDao themeConfigDao;

    @Autowired
    private IEnterpriseAppConfigDao enterpriseAppConfigDao;

    @Autowired
    private IEnterpriseAppConfigService enterpriseAppConfigService;

    @Autowired
    private IIndustryService industryService;

    @Autowired
    LogTemplate logTemplate;
    @Autowired
    IAccountService accountService;

    @Override
    public Page page(EnterpriseQuery enterpriseQuery, Account account, Page page) {
        List<Enterprise> enterpriseInfos = enterpriseService.list(enterpriseQuery, account);
        if (enterpriseInfos.isEmpty()) {
            return page;
        }
        List<Integer> enterpriseIds = enterpriseInfos.stream().map(Enterprise::getId).collect(Collectors.toList());
        return enterpriseConfigDao.page(page, enterpriseIds, enterpriseQuery.getName());
    }

    @Override
    public Boolean entConfigExistCheck(EnterpriseConfigDTO enterpriseConfigDTO) {
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        if (null != enterpriseConfigDTO.getId()) {
            enterpriseConfigQueryWrapper.eq("id", enterpriseConfigDTO.getId());
            enterpriseConfigQueryWrapper.eq("industry_id", enterpriseConfigDTO.getIndustryId());
            enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
            enterpriseConfigQueryWrapper.eq("link_code", enterpriseConfigDTO.getLinkCode());
        } else {
            enterpriseConfigQueryWrapper.eq("industry_id", enterpriseConfigDTO.getIndustryId());
            enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
            enterpriseConfigQueryWrapper.eq("link_code", enterpriseConfigDTO.getLinkCode());
        }
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        return enterpriseConfig == null;
    }

    @Override
    public Boolean linkCodeAndEntExistCheck(EnterpriseConfigDTO enterpriseConfigDTO) {
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        if (null != enterpriseConfigDTO.getId()) {
            enterpriseConfigQueryWrapper.eq("id", enterpriseConfigDTO.getEnterpriseId());
            enterpriseConfigQueryWrapper.eq("industry_id", enterpriseConfigDTO.getIndustryId());
            enterpriseConfigQueryWrapper.eq("link_code", enterpriseConfigDTO.getLinkCode());
        } else {
            enterpriseConfigQueryWrapper.eq("industry_id", enterpriseConfigDTO.getIndustryId());
            enterpriseConfigQueryWrapper.eq("link_code", enterpriseConfigDTO.getLinkCode());
        }
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        return enterpriseConfig == null;
    }

    @Override
    public Boolean linkCodeExistCheck(EnterpriseConfigDTO enterpriseConfigDTO) {
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("industry_id", enterpriseConfigDTO.getIndustryId());
        enterpriseConfigQueryWrapper.eq("link_code", enterpriseConfigDTO.getLinkCode());
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        return enterpriseConfig == null;
    }

    @Override
    public Boolean entExistCheck(EnterpriseConfigDTO enterpriseConfigDTO) {
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        return enterpriseConfig == null;
    }

    @Override
    public ResultJson update(Short industryId, EnterpriseConfigDTO enterpriseConfigDTO) {
        EnterpriseConfig enterpriseConfig = new EnterpriseConfig();
        BeanUtils.copyProperties(enterpriseConfigDTO, enterpriseConfig);
        if (enterpriseConfig.getPlatformStyle() != 3) {
            enterpriseConfig.setSlideUrls("");
        }
        if (null == enterpriseConfigDTO.getId()) {
            save(enterpriseConfig);
        } else {
            updateById(enterpriseConfig);
        }
        // 移动端产品先删后增
        QueryWrapper<EnterpriseAppConfig> entAppConfQuery = new QueryWrapper<>();
        entAppConfQuery.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
        enterpriseAppConfigDao.delete(entAppConfQuery);
        List<EnterpriseAppConfig> appConfigList = enterpriseConfigDTO.getAppConfigList();
        if (!CollectionUtils.isEmpty(appConfigList)) {
            for (EnterpriseAppConfig enterpriseAppConfig : appConfigList) {
                enterpriseAppConfig.setIndustryId(industryId);
                enterpriseAppConfig.setEnterpriseId(enterpriseConfigDTO.getEnterpriseId());
            }
            enterpriseAppConfigService.saveBatch(appConfigList);
        }
        return ResultJson.success("更新成功");
    }


    @Override
    public ResultJson findEntConf(Short industryId, Integer enterpriseId, String linkCode) {
        // 检查平台信息
        if (null != industryId) {
            Industry industry = industryService.getById(industryId);
            if (null == industry) {
                return ResultJson.fail("参数错误，平台信息不存在");
            }
        }
        QueryWrapper<ThemeConfig> themeConfQueryWrapper = new QueryWrapper<>();
        // 不传企业id、访问地址编码linkCode，则返回业态默认配置（一般应用在未登录）
        if (null == enterpriseId && (null == linkCode || linkCode.trim().length() == 0)) {
            themeConfQueryWrapper.eq("industry_id", industryId);
            ThemeConfig themeConf = themeConfigDao.selectOne(themeConfQueryWrapper);
            if (null == themeConf) {
                return ResultJson.fail("业态默认配置不存在");
            }
            EnterpriseConfig enterpriseConf = new EnterpriseConfig();
            enterpriseConf.setLogoUrl(themeConf.getLogo());
            enterpriseConf.setBackgroundUrl(themeConf.getBackgroundUrl());
            enterpriseConf.setIcoUrl(themeConf.getIcoUrl());
            enterpriseConf.setThemeColor(themeConf.getThemeColor());
            // 分配默认移动端产品配置
            List<EnterpriseAppConfig> enterpriseAppConfigList = getEnterpriseAppConfig(industryId, null);
            enterpriseConf.setAppConfigList(enterpriseAppConfigList);
            return ResultJson.success(enterpriseConf);
        }
        QueryWrapper<EnterpriseConfig> entConfQueryWrapper = new QueryWrapper<>();
        Enterprise enterprise = new Enterprise();
        if (null != enterpriseId) {
            enterprise = enterpriseDao.selectById(enterpriseId);
            if (null == enterprise) {
                return ResultJson.fail("该企业不存在");
            }
            entConfQueryWrapper.eq("enterprise_id", enterpriseId);
        } else {
            entConfQueryWrapper.eq("industry_id", industryId);
        }
        if (null != linkCode) {
            entConfQueryWrapper.eq("link_code", linkCode);
        }
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(entConfQueryWrapper);
        if (null == enterpriseConfig) {
            // 分配业态默认主题配置
            themeConfQueryWrapper.eq("industry_id", industryId);
            ThemeConfig themeConf = themeConfigDao.selectOne(themeConfQueryWrapper);
            if (null == themeConf) {
                return ResultJson.fail("业态默认配置不存在");
            }
            EnterpriseConfig enterpriseConf = new EnterpriseConfig();
            enterpriseConf.setLogoUrl(themeConf.getLogo());
            enterpriseConf.setBackgroundUrl(themeConf.getBackgroundUrl());
            enterpriseConf.setIcoUrl(themeConf.getIcoUrl());
            enterpriseConf.setThemeColor(themeConf.getThemeColor());
            // 分配默认移动端产品配置
            List<EnterpriseAppConfig> enterpriseAppConfigList = getEnterpriseAppConfig(industryId, enterprise.getId());
            enterpriseConf.setAppConfigList(enterpriseAppConfigList);
            return ResultJson.success(enterpriseConf);
        } else {
            List<EnterpriseAppConfig> enterpriseAppConfigList = getEnterpriseAppConfig(enterpriseConfig.getIndustryId(), enterpriseConfig.getEnterpriseId());
            enterpriseConfig.setAppConfigList(enterpriseAppConfigList);
            enterpriseConfig.setEnterpriseName(enterprise.getName());
            return ResultJson.success(enterpriseConfig);
        }
    }


    /**
     * 返回移动端产品配置
     * @param industryId
     * @param enterpriseId
     * @return
     */
    public List<EnterpriseAppConfig> getEnterpriseAppConfig(Short industryId, Integer enterpriseId) {
        // 如果企业id为空，则返回默认业态移动端产品配置
        QueryWrapper<EnterpriseAppConfig> entAppConfQuery = new QueryWrapper<>();
        List<EnterpriseAppConfig> enterpriseAppConfigList = new ArrayList<>();
        if (null == enterpriseId) {
            entAppConfQuery.eq("industry_id", industryId);
            entAppConfQuery.isNull("enterprise_id");
            enterpriseAppConfigList = enterpriseAppConfigDao.selectList(entAppConfQuery);
        } else {
            entAppConfQuery.eq("industry_id", industryId);
            entAppConfQuery.eq("enterprise_id", enterpriseId);
            enterpriseAppConfigList = enterpriseAppConfigDao.selectList(entAppConfQuery);
            // 如果企业查询为空则补充业态默认移动端产品配置
            if (CollectionUtils.isEmpty(enterpriseAppConfigList)) {
                QueryWrapper<EnterpriseAppConfig> entAppConfQueryDefault = new QueryWrapper<>();
                entAppConfQueryDefault.eq("industry_id", industryId);
                entAppConfQueryDefault.isNull("enterprise_id");
                enterpriseAppConfigList = enterpriseAppConfigDao.selectList(entAppConfQueryDefault);
            }
        }
        return enterpriseAppConfigList;
    }


    @Override
    public EnterpriseConfig findByEntId(Integer enterpriseId) {
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseId);
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        if (null == enterpriseConfig) {
            enterpriseConfig = new EnterpriseConfig();
            Enterprise enterprise = enterpriseService.findById(enterpriseId);
            enterpriseConfig.setEnterpriseName(enterprise.getName());
        }
        return enterpriseConfig;
    }


    /**
     * 会话超时时间设置
     *
     * @param enterpriseConfigDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultJson setSessionTime(EnterpriseConfigDTO enterpriseConfigDTO) {
        Optional.ofNullable(enterpriseConfigDTO.getEnterpriseId()).orElseThrow(() -> new DataException("缺少企业id参数"));
        Optional.ofNullable(enterpriseConfigDTO.getSessionLimitTime()).orElseThrow(() -> new DataException("缺少会话超时时间参数"));
        Optional.ofNullable(enterpriseConfigDTO.getLimitTimeUnit()).orElseThrow(() -> new DataException("缺少会话超时时间单位参数"));
        Integer sessionLimitTime = enterpriseConfigDTO.getSessionLimitTime();
        Integer limitTimeUnit = enterpriseConfigDTO.getLimitTimeUnit();
        if (limitTimeUnit!=Unit.MINUTE.code && limitTimeUnit!=Unit.HOUR.code){
            throw new DataException("不支持当前超时时间单位类型");
        }
        String timeUnit = "";
        if (Unit.MINUTE.code == limitTimeUnit) {
            timeUnit = Unit.MINUTE.getName();
            if (15 > sessionLimitTime || 1440 < sessionLimitTime) {
                throw new DataException("请输入15~1440之间的整数");
            }
        }
        if (Unit.HOUR.code == limitTimeUnit) {
            timeUnit = Unit.HOUR.getName();
            if (1 > sessionLimitTime || 24 < sessionLimitTime) {
                throw new DataException("请输入1~24之间的整数");
            }
        }
        Integer enterpriseId = enterpriseConfigDTO.getEnterpriseId();
        Enterprise enterprise = enterpriseService.findById(enterpriseId);
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        String operateRecord = "";
        if (null == enterpriseConfig) {
            operateRecord = "修改企业" + "【" + enterprise.getName() + "】 会话超时时间," + "从" + ENT_SESSION_LIMIT_TIME + Unit.MINUTE.getName() + "改为" + sessionLimitTime + timeUnit;
        } else {
           Integer limitTimeUnitDb = enterpriseConfig.getLimitTimeUnit();
           String timeUnitDb = "";
           if (Unit.MINUTE.code == limitTimeUnitDb) {
               timeUnitDb = Unit.MINUTE.getName();
           }
           if (Unit.HOUR.code == limitTimeUnitDb) {
               timeUnitDb = Unit.HOUR.getName();
           }
           operateRecord = "修改企业" + "【" + enterprise.getName() + "】 会话超时时间," + "从" + enterpriseConfig.getSessionLimitTime() + timeUnitDb + "改为" + sessionLimitTime + timeUnit;
        }
        //设置会话超时时间
        setSessionLimitTime(enterpriseConfigDTO);
        //记录日志
        sessionConfigLogRecord(LogOperationTypeEnum.UPDATE, operateRecord, enterprise.getId());
        return ResultJson.success("设置成功");
    }

    /**
     * 记录会话超时设置日志
     *
     * @param logOperationTypeEnum
     * @param operateContent
     * @param entId
     */
    public void sessionConfigLogRecord(LogOperationTypeEnum logOperationTypeEnum, String operateContent, Integer entId) {
        OperateLog operateLog = new OperateLog();
        operateLog.setMenu("安全设置");
        operateLog.setOperateType(logOperationTypeEnum.getType());
        operateLog.setOperateContent(operateContent);
        operateLog.setIp(ThreadLocalUtil.getIp());
        operateLog.setIndustryId(ThreadLocalUtil.getIndustryId());
        operateLog.setEnterpriseId(entId);
        Account operateAccount = ThreadLocalUtil.getAccount();
        if (null != operateAccount) {
            operateLog.setIndustryId(operateAccount.getIndustryId());
            operateLog.setAccountId(operateAccount.getId());
            operateLog.setLoginName(operateAccount.getLoginName());
            operateLog.setName(operateAccount.getName());
            //填充企业ids+项目ids
            List<Enterprise> enterprises = enterpriseService.list(null,operateAccount);
            if (!org.springframework.util.CollectionUtils.isEmpty(enterprises)){
                operateLog.setEnterpriseIds(enterprises.stream().map(Enterprise::getId).collect(Collectors.toList()));
            }
            List<AccountDetailDTO> projectInfoList = accountService.getAccountProjectInfoByIdList(Collections.singletonList(operateAccount.getId()));
            operateLog.setProjectIds(projectInfoList.stream().map(AccountDetailDTO::getProjectId).collect(Collectors.toList()));
            if (!org.springframework.util.CollectionUtils.isEmpty(projectInfoList)){
                operateLog.setProjectIds(projectInfoList.stream().map(AccountDetailDTO::getProjectId).collect(Collectors.toList()));
            }
        }
        logTemplate.addOperateLog(operateLog);
    }


    @Override
    public EnterpriseConfig getSessionTime(Integer enterpriseId) {
        Enterprise enterprise = enterpriseService.findById(enterpriseId);
        if (null == enterprise) {
            throw new BusinessException("当前企业信息不存在");
        }
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseId);
        EnterpriseConfig sessionTimeConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        if (Objects.isNull(sessionTimeConfig)) {
            //获取业态级别的默认配置作为数据填充
            QueryWrapper<ThemeConfig> themeConfQueryWrapper = new QueryWrapper<>();
            themeConfQueryWrapper.eq("industry_id", enterprise.getIndustryId());
            ThemeConfig themeConf = themeConfigDao.selectOne(themeConfQueryWrapper);
            // Optional.ofNullable(themeConf).orElseThrow(() -> new DataException("不存在业态默认主题配置"));
            EnterpriseConfig enterpriseConfInsert = new EnterpriseConfig();
            if (null != themeConf) {
                enterpriseConfInsert.setLogoUrl(themeConf.getLogo());
                enterpriseConfInsert.setBackgroundUrl(themeConf.getBackgroundUrl());
                enterpriseConfInsert.setIcoUrl(themeConf.getIcoUrl());
                enterpriseConfInsert.setThemeColor(themeConf.getThemeColor());
            }
            enterpriseConfInsert.setIndustryId(enterprise.getIndustryId());
            enterpriseConfInsert.setEnterpriseId(enterprise.getId());
            enterpriseConfInsert.setEnterpriseName(enterprise.getName());
            enterpriseConfInsert.setSessionLimitTime(ENT_SESSION_LIMIT_TIME);
            enterpriseConfInsert.setLimitTimeUnit(ENT_SESSION_LIMIT_TIME_UNIT);
            try {
                save(enterpriseConfInsert);
            }catch (Exception e){
                throw new DataException(e.getMessage());
            }
            return enterpriseConfInsert;
        }
        if (null == sessionTimeConfig.getSessionLimitTime()) {
            //填充默认值
            EnterpriseConfig enterpriseConfigUpdate = new EnterpriseConfig();
            enterpriseConfigUpdate.setEnterpriseId(enterpriseId);
            enterpriseConfigUpdate.setSessionLimitTime(ENT_SESSION_LIMIT_TIME);
            enterpriseConfigUpdate.setLimitTimeUnit(ENT_SESSION_LIMIT_TIME_UNIT);
            enterpriseConfigUpdate.setId(sessionTimeConfig.getId());
            UpdateWrapper<EnterpriseConfig> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", sessionTimeConfig.getId());
            enterpriseConfigDao.update(enterpriseConfigUpdate, updateWrapper);
            return enterpriseConfigUpdate;
        }
        return sessionTimeConfig;
    }


    /**
     * 获取当前企业的配置参数，如果没有会默认存入一条企业级别数据
     *
     * @param enterpriseConfigDTO
     * @return
     */
    public void setSessionLimitTime(EnterpriseConfigDTO enterpriseConfigDTO) {
        Enterprise enterprise = enterpriseService.findById(enterpriseConfigDTO.getEnterpriseId());
        Optional.ofNullable(enterprise).orElseThrow(() -> new DataException("不存在当前企业信息"));
        QueryWrapper<EnterpriseConfig> enterpriseConfigQueryWrapper = new QueryWrapper<>();
        enterpriseConfigQueryWrapper.eq("enterprise_id", enterpriseConfigDTO.getEnterpriseId());
        EnterpriseConfig enterpriseConfig = enterpriseConfigDao.selectOne(enterpriseConfigQueryWrapper);
        if (null == enterpriseConfig) {
            //默认插入初始化配置参数
            //获取业态级别的默认配置作为数据填充
            QueryWrapper<ThemeConfig> themeConfQueryWrapper = new QueryWrapper<>();
            themeConfQueryWrapper.eq("industry_id", enterprise.getIndustryId());
            ThemeConfig themeConf = themeConfigDao.selectOne(themeConfQueryWrapper);
            // Optional.ofNullable(themeConf).orElseThrow(() -> new DataException("不存在业态默认主题配置"));
            EnterpriseConfig enterpriseConfInsert = new EnterpriseConfig();
            if (null == themeConf) {
                enterpriseConfInsert.setLogoUrl(themeConf.getLogo());
                enterpriseConfInsert.setBackgroundUrl(themeConf.getBackgroundUrl());
                enterpriseConfInsert.setIcoUrl(themeConf.getIcoUrl());
                enterpriseConfInsert.setThemeColor(themeConf.getThemeColor());
            }
            enterpriseConfInsert.setIndustryId(enterprise.getIndustryId());
            enterpriseConfInsert.setEnterpriseId(enterprise.getId());
            enterpriseConfInsert.setEnterpriseName(enterprise.getName());
            enterpriseConfInsert.setSessionLimitTime(enterpriseConfigDTO.getSessionLimitTime());
            enterpriseConfInsert.setLimitTimeUnit(enterpriseConfigDTO.getLimitTimeUnit());
            save(enterpriseConfInsert);
        } else {
            //更新初始化配置参数
            EnterpriseConfig enterpriseConfigUpdate = new EnterpriseConfig();
            enterpriseConfigUpdate.setSessionLimitTime(enterpriseConfigDTO.getSessionLimitTime());
            enterpriseConfigUpdate.setLimitTimeUnit(enterpriseConfigDTO.getLimitTimeUnit());
            enterpriseConfigUpdate.setId(enterpriseConfig.getId());
            UpdateWrapper<EnterpriseConfig> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", enterpriseConfig.getId());
            enterpriseConfigDao.update(enterpriseConfigUpdate, updateWrapper);
        }
    }

}

